package org.aeon.dao.impl;

import org.aeon.annotation.Incomplete;
import org.aeon.dao.UserMessageDao;
import org.aeon.entity.ChatMessage;
import org.aeon.entity.StatisticsRecord;
import org.aeon.utils.FileIoUtil;

import java.io.File;
import java.nio.file.FileSystems;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author: MissingAeon
 * @date: 2024/1/26 14:02
 * @description:
 */
public class UserMessageDaoImpl implements UserMessageDao {

    private static final String PATH = System.getProperty("user.home") +
            File.separator + "Documents" + File.separator + "ChatWithEach" +
            File.separator + "data" + File.separator + "chatHistory" + File.separator;
    private static final String SUFFIX = ".json";
    private static final SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");

    /**
     * 拼接为完整路径用于文件写入
     *
     * @param userId
     * @param date
     * @return
     */
    private static String fullPath(Long userId, Date date) {
        return PATH + userId + FileSystems.getDefault().getSeparator() + yyyyMMdd.format(date) + SUFFIX;
    }

    /**
     * 拼接为完整路径用于文件写入
     *
     * @param userId
     * @return
     */
    private static String fullPath(Long userId) {
        return PATH + userId + FileSystems.getDefault().getSeparator() + "statistics-record" + SUFFIX;
    }

    /**
     * 更新记录
     *
     * @param userId
     * @param date
     * @param consumer
     */
    private static void updateRecord(String path, Long userId, String date, Consumer<StatisticsRecord.Item> consumer) {
        // 读取
        final Set<StatisticsRecord> records = new HashSet<>(
                Objects.requireNonNull(FileIoUtil.read(path, StatisticsRecord.class)));
        // 获取当天记录
        final StatisticsRecord statisticsRecord = records.stream()
                .filter(record -> record.getDateTime().equals(date)).findAny()
                .orElse(new StatisticsRecord(date));
        // 获取用户记录
        final StatisticsRecord.Item recordItem = statisticsRecord.getRecords().stream()
                .filter(item -> Objects.equals(item.getTarget(), userId)).findAny()
                .orElse(new StatisticsRecord.Item(userId));
        // 操作记录
        consumer.accept(recordItem);
        // 覆盖
        statisticsRecord.getRecords().add(recordItem);
        records.add(statisticsRecord);
        // 覆盖写入
        FileIoUtil.write(path, new ArrayList<>(records));
    }

    private static Map<String, StatisticsRecord.Item> readRecord(String path, Long userId) {
        // 读取
        final Set<StatisticsRecord> records = new HashSet<>(
                Objects.requireNonNull(FileIoUtil.read(path, StatisticsRecord.class)));
        // 获取当天记录
        final Map<String, StatisticsRecord.Item> map = records.stream()
                .filter(record -> record.getRecords().stream().anyMatch(item -> Objects.equals(item.getTarget(), userId)))
                .collect(Collectors.toMap(StatisticsRecord::getDateTime, record -> record.getRecords().stream()
                        .filter(item -> userId.equals(item.getTarget()))
                        .findAny().orElseThrow()));
        return map;
    }

    @Override
    public int insert(Long userId, ChatMessage message) {
        final Date date = new Date();
        if (FileIoUtil.jsonWriteTail(fullPath(userId, date), message)) {
            // 更新统计
            updateRecord(fullPath(userId), message.getFrom() == userId ? message.getTo() : message.getFrom(),
                    yyyyMMdd.format(date), item -> item.setCount(item.getCount() + 1));
            return 1;
        }
        return 0;
    }

    @Override
    public int batchInsertion(Long userId, List<ChatMessage> chatMessages) {
        if (FileIoUtil.jsonWriteTail(fullPath(userId, new Date()), chatMessages)) {
            return chatMessages.size();
        }
        return 0;
    }

    @Incomplete
    @Override
    public int batchDeletion(Predicate<ChatMessage> condition) {
        return 0;
    }

    @Override
    public List<ChatMessage> read(Long userId, Long targetId, Date date) {
        final String fullPath = fullPath(userId, date);
        if (FileIoUtil.fileLength(fullPath) == 0) {
            return new ArrayList<>();
        }
        if (targetId < 0) {
            return FileIoUtil.read(fullPath, ChatMessage.class).stream()
                    .filter(message -> message.getTo() == targetId)
                    .toList();
        } else if (targetId > 0) {
            return FileIoUtil.read(fullPath, ChatMessage.class).stream()
                    .filter(message -> (message.getFrom() == userId || message.getFrom() == 0) && message.getTo() == targetId ||
                            message.getFrom() == targetId && message.getTo() == userId)
                    .toList();
        }
        throw new RuntimeException("非法id");
    }

    @Override
    public List<ChatMessage> read(Long userId, Long targetId, Long start, int count) {
        final Map<String, StatisticsRecord.Item> itemMap = readRecord(fullPath(userId), targetId);
        List<ChatMessage> messages = new ArrayList<>(count);
        // 日历
        Calendar calendar = Calendar.getInstance();
        // 调整到指定时间
        if (start != null) calendar.setTimeInMillis(start);
        while (!itemMap.isEmpty()) {
            // 去除读到的消息
            itemMap.remove(yyyyMMdd.format(calendar.getTime()));
            // 读取
            List<ChatMessage> messageList = read(userId, targetId, calendar.getTime());
            // 定位消息
            if (start != null) {
                messageList = messageList.stream().filter(m -> m.getCreationTime() < start).toList();
            }
            // 获取消息
            for (int i = messageList.size() - 1; i >= 0; i--) {
                if (count-- == 0) {
                    return messages;
                }
                messages.add(messageList.get(i));
            }
            // 调整时间
            calendar.add(Calendar.DAY_OF_MONTH, -1);
        }
        // Collections.reverse(messages);
        return messages;
    }

    @Override
    public List<ChatMessage> read(Long userId, Predicate<ChatMessage> condition, final Date asOfDate) {
        int count = 0;
        // 日历
        Calendar calendar = Calendar.getInstance();
        final ArrayList<ChatMessage> list = new ArrayList<>();
        // 判断之前
        while (calendar.after(asOfDate)) {
            // 控制可查询天数
            if (count++ > 30) break;
            final String path = fullPath(userId, calendar.getTime());
            // 向前翻一天
            calendar.add(Calendar.DAY_OF_MONTH, -1);
            // 判断有数据
            if (FileIoUtil.fileLength(path) > 0) {
                final List<ChatMessage> history = FileIoUtil.read(path, ChatMessage.class);
                // 读取失败也跳过
                if (history.isEmpty()) continue;
                // 过滤并追加数据
                history.stream().filter(condition).forEach(list::add);
            }
        }
        return list;
    }
}
